package com.example.demo.controller;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.example.demo.config.MqttBroker;
import com.example.demo.entity.*;
import com.example.demo.service.*;
import com.example.demo.util.GetMessage;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/api/order")
@RequiredArgsConstructor
@Component
public class PurchaseOrderController {
    @Value("${codeSystem.ip}")
    private String ip;

    private static final ObjectMapper objectMapper = new ObjectMapper();
    private final CodeHistoryService codeHistoryService;
    private final PurchaseOrderService purchaseOrderService;
    private final SerialNumberService serialNumberService;
    private final PurchaseApplyOrderService purchaseApplyOrderService;
    private final TrainInfoService trainInfoService;
    private final UserProductinfoService userProductinfoService;
    private final CustomRulesService customRulesService;
    private final CodeAssignmentRulesService codeAssignmentRulesService;

    @CrossOrigin(origins = "*", maxAge = 3600)
    @PostMapping("/save1")
    public GetMessage insert(@RequestBody PurchaseOrder purchaseOrder) throws JsonProcessingException, MqttException {
        purchaseOrder.setOrdertime(Util.getNowTime());
        purchaseOrder.setIspayment("0");
        purchaseOrder.setIssignbuy("0");
        purchaseOrder.setIssignseller("0");
        purchaseOrder.setDeliverydate(getDeliveryDate(purchaseOrder.getDeliverytime(), Util.getNowDate()));
        String code = codeHistoryService.make(purchaseOrder.getUserid(), "orderSave", purchaseOrder.getTrainingid(), 2, null, "MA.156.110116.1007/61.12000000.2501");
        purchaseOrder.setIdentifycode(code);
        purchaseOrder.setOrderstate("0");
        PurchaseOrder p = purchaseOrderService.selectByInfo(purchaseOrder.getUserid(), purchaseOrder.getTrainingid(), purchaseOrder.getOrdernumber(), null, null);
        if (p != null) {
            return new GetMessage("该单号已下单", "500", "");
        }

        boolean bol = purchaseOrderService.save(purchaseOrder);
        if (bol) {
            Map<String, Object> map = new HashMap<>();
            map.put("type", "orderSave");
            map.put("trainingId", purchaseOrder.getTrainingid());
            String payload = objectMapper.writeValueAsString(map);
            MqttBroker.mqttClient.publish("StepInfo/supply/" + purchaseOrder.getUserid(), new MqttMessage(payload.getBytes(StandardCharsets.UTF_8)));
            return new GetMessage("成功", "200", "");
        }
        return new GetMessage("失败", "500", "");
    }


    public static String getDeliveryDate(String week, String time) {
        LocalDate date = LocalDate.parse(time);
        LocalDate newDate = null;
        if (week.equals("一周")) {
            newDate = date.plusWeeks(1);
        } else if (week.equals("二周")) {
            newDate = date.plusWeeks(2);
        } else if (week.equals("三周")) {
            newDate = date.plusWeeks(3);
        } else if (week.equals("四周")) {
            newDate = date.plusWeeks(4);
        }
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        String formattedDate = newDate.format(formatter);
        return formattedDate;
    }

    public GetMessage addInfo(PurchaseOrder purchaseOrder, String appId) throws JsonProcessingException, UnsupportedEncodingException {
        String model = "GYL-XD";
        Map<String, Object> infoList = Util.getJsonStr(appId, model);
        ObjectMapper mapper = new ObjectMapper();
        String jsonString = mapper.writeValueAsString(infoList);
        TrainInfo trainInfo = trainInfoService.selectByUserId(purchaseOrder.getUserid()).get(0);
        Map<String, String> headerList = new HashMap<>();
        headerList.put("X-Access-Key", trainInfo.getAccesskey());
        String code = "";
        UserProductinfo userProductinfo = new UserProductinfo();
        UserProductinfo u = userProductinfoService.selectProductInfoOne(purchaseOrder.getUserid(), appId, null);
        if (u == null) {
            String res = Util.postUrl(ip + "/api/client/model", headerList, jsonString);
            JSONObject jsonResponse = new JSONObject(res);
            if (jsonResponse.get("code").equals("SUCCESS")) {
                JSONObject jsonResponse1 = new JSONObject(jsonResponse.get("data"));
                code = jsonResponse1.get("code").toString();
                userProductinfo.setUserid(purchaseOrder.getUserid());
                userProductinfo.setProductinfo("");
                userProductinfo.setAppid(appId);
                userProductinfo.setTrainingid(purchaseOrder.getTrainingid());
                userProductinfo.setProductmodel(model);
                userProductinfo.setCategorycode(code);
                userProductinfo.setModelid(jsonResponse1.get("id").toString());
                userProductinfoService.save(userProductinfo);
                return new GetMessage("成功", "200", code);
            } else {
                return new GetMessage(jsonResponse.get("message").toString(), "500", code);
            }

        } else {
            return new GetMessage("已新增产品" + u.getProductmodel(), "500", code);
        }
    }

    public GetMessage register(String userId, String appId) throws IOException {
        UserProductinfo userProductinfo = userProductinfoService.selectProductInfoOne(userId, appId, null);
        Map<String, String> headerList = new HashMap<>();
        TrainInfo trainInfo = trainInfoService.selectByUserId(userId).get(0);
        headerList.put("X-Access-Key", trainInfo.getAccesskey());
        String res = Util.putUrl(ip + "/api/client/model/" + userProductinfo.getModelid() + "/register", headerList);
        JSONObject jsonResponse = new JSONObject(res);
        if (jsonResponse.get("code").equals("SUCCESS")) {
            JSONObject jsonResponse1 = new JSONObject(jsonResponse.get("data"));
            String code = jsonResponse1.get("code").toString();

            return new GetMessage("成功", "200", code);
        }
        return new GetMessage(jsonResponse.get("message").toString(), "500", "");
    }

    public GetMessage addCustom(String userId, String trainingId, String appId) throws JsonProcessingException {
        CustomRules customRules = new CustomRules();
        String name = "自定义-采购";
        String rule = "[datetime|yyyyMMddHHmmss].[random|4].[number|9999]";
        String ruleDesc = "批次号.随机码.序列号";
        Map<String, Object> jsonMap = new HashMap<>();
        jsonMap.put("name", name);
        jsonMap.put("rule", rule);
        jsonMap.put("ruleDesc", ruleDesc);

        TrainInfo trainInfo = trainInfoService.selectByUserId(userId).get(0);
        Map<String, String> headerList = new HashMap<>();
        headerList.put("X-Access-Key", trainInfo.getAccesskey());
        ObjectMapper objectMapper = new ObjectMapper();
        String jsonString = objectMapper.writeValueAsString(jsonMap);
        String res = Util.postUrl(ip + "/api/client/custom-rule", headerList, jsonString);
        JSONObject jsonResponse = new JSONObject(res);
        if (jsonResponse.get("code").equals("SUCCESS")) {
            JSONObject jsonResponse1 = new JSONObject(jsonResponse.get("data"));
            customRules.setRuleid(jsonResponse1.get("id"));
            customRules.setRulename(name);
            customRules.setRule(rule);
            customRules.setRuledesc(ruleDesc);
            customRules.setUserid(userId);
            customRules.setTrainingid(trainingId);
            customRules.setAppid(appId);
            boolean bol = customRulesService.save(customRules);
            if (bol) {
                return new GetMessage("成功", "200", customRules);
            }
        }

        return new GetMessage("失败", "500", null);
    }

    public GetMessage addRule(String userId, String trainingId, String appId) throws JsonProcessingException {
        UserProductinfo userProductinfo = userProductinfoService.selectProductInfoOne(userId, appId, null);
//        CodeAssignmentRules codeAssignmentRules=codeAssignmentRulesService.select(userId,"purchaseOrder",trainingId,"0").get(0);
        CustomRules customRules = customRulesService.select(userId, appId, null).get(0);
        if (customRules == null) {
            return new GetMessage("未找到自定义规则", "500", null);
        }
        String name = "采购";

        Map<String, Object> bjsonMap = new HashMap<>();
        bjsonMap.put("name", name);
        bjsonMap.put("modelId", userProductinfo.getModelid());
        bjsonMap.put("customRuleId", customRules.getRuleid());
        String bjsonString = objectMapper.writeValueAsString(bjsonMap);

        TrainInfo trainInfo = trainInfoService.selectByUserId(userId).get(0);
        Map<String, String> headerList = new HashMap<>();
        headerList.put("X-Access-Key", trainInfo.getAccesskey());
        String bres = Util.postUrl(ip + "/api/client/identification-code-rule", headerList, bjsonString);
        JSONObject bjsonResponse = new JSONObject(bres);
        if (!(bjsonResponse.get("code").equals("SUCCESS"))) {
            return new GetMessage(bjsonResponse.get("message").toString(), "500", null);
        }

        JSONObject bdata = new JSONObject(bjsonResponse.get("data"));
        CodeAssignmentRules codeAssignmentRules = new CodeAssignmentRules();
        codeAssignmentRules.setRulename(name);
        codeAssignmentRules.setCodingid(customRules.getRuleid());
        codeAssignmentRules.setRuletype("0");
        codeAssignmentRules.setAppid(appId);
        codeAssignmentRules.setTrainingid(trainingId);
        codeAssignmentRules.setUserid(userId);
        codeAssignmentRules.setRuleid(bdata.get("id").toString());
        codeAssignmentRules.setCodetype("MA");
        codeAssignmentRules.setUserid(userId);
        boolean bol = codeAssignmentRulesService.save(codeAssignmentRules);
        if (bol) {
            return new GetMessage("成功", "200", codeAssignmentRules);
        }
        return new GetMessage("失败", "500", null);
    }

    public GetMessage getCode(String userId, String trainingId, String appId, Integer ruleId) throws JsonProcessingException {
        String code = "";
        TrainInfo trainInfo = trainInfoService.selectByUserId(userId).get(0);
        Map<String, String> headerList = new HashMap<>();
        headerList.put("X-Access-Key", trainInfo.getAccesskey());

        Map<String, Object> jsonMap = new HashMap<>();
        jsonMap.put("count", 1);

        CodeAssignmentRules codeAssignmentRules = codeAssignmentRulesService.selectById(ruleId);

        ObjectMapper objectMapper = new ObjectMapper();
        String jsonString = objectMapper.writeValueAsString(jsonMap);
        String res = Util.postUrl(ip + "/api/client/identification-code-record/" + codeAssignmentRules.getRuleid() + "/batch", headerList, jsonString);

        JSONObject jsonResponse = new JSONObject(res);
        if (jsonResponse.get("code").equals("SUCCESS")) {
            JSONObject data = new JSONObject(jsonResponse.get("data"));
            JSONArray jsonArray = new JSONArray(data.get("codes"));
            code = jsonArray.get(0).toString();
            CodeHistory codeHistory = new CodeHistory();
            codeHistory.setCodeinfo(code);
            codeHistory.setRulesid(ruleId);
            codeHistory.setTrainingid(trainingId);
            codeHistory.setUserid(userId);
            codeHistory.setAppid(appId);
            codeHistory.setRuletype(1);
            codeHistoryService.save(codeHistory);

            return new GetMessage("成功", "200", code);
        }
        return new GetMessage(jsonResponse.get("message").toString(), "500", "");
    }

    @CrossOrigin(origins = "*", maxAge = 3600)
    @PostMapping("/save")
    public GetMessage save(@RequestBody PurchaseOrder purchaseOrder) throws IOException, MqttException {
        PurchaseOrder p = purchaseOrderService.selectByInfo(purchaseOrder.getUserid(), purchaseOrder.getTrainingid(), null, null, purchaseOrder.getIspart());
        if (p != null) {
            return new GetMessage("已下单", "500", "");
        }


        List<UserProductinfo> listUser = userProductinfoService.selectProductInfo(purchaseOrder.getUserid(), "order", null);
        if(listUser.size()==0){
            //新增型号
            GetMessage mes1 = addInfo(purchaseOrder, "order");
            if (!(mes1.getCode().equals("200"))) {
                return mes1;
            }
            //注册
            GetMessage mes2 = register(purchaseOrder.getUserid(), "order");
            if (!(mes2.getCode().equals("200"))) {
                return mes2;
            }
        }

        //添加规则
        List<CodeAssignmentRules> codeList = codeAssignmentRulesService.select(purchaseOrder.getUserid(), "order", null, "0");
        Integer id = 0;
        if (codeList.size()==0) {
            GetMessage mes3 = addCustom(purchaseOrder.getUserid(), purchaseOrder.getTrainingid(), "order");
            if (!(mes3.getCode().equals("200"))) {
                return mes3;
            }
            GetMessage mes4 = addRule(purchaseOrder.getUserid(), purchaseOrder.getTrainingid(), "order");
            if (!(mes4.getCode().equals("200"))) {

                return mes4;
            }
            CodeAssignmentRules codeAssignmentRules = (CodeAssignmentRules) mes4.getData();
            id = (Integer) (codeAssignmentRules.getId());
        } else {
            id= (Integer) (codeList.get(0).getId());
        }

        //赋码
        GetMessage mes5 = getCode(purchaseOrder.getUserid(), purchaseOrder.getTrainingid(), "order", id);
        if (!(mes5.getCode().equals("200"))) {
            return mes5;
        }
        purchaseOrder.setOrdertime(Util.getNowTime());
        String code = mes5.getData().toString();
        purchaseOrder.setOrdertime(Util.getNowTime());
        purchaseOrder.setIspayment("0");
        purchaseOrder.setIssignbuy("0");
        purchaseOrder.setIssignseller("0");
        purchaseOrder.setIdentifycode(code);
        purchaseOrder.setOrderstate("0");
        purchaseOrder.setDeliverydate(getDeliveryDate(purchaseOrder.getDeliverytime(), Util.getNowDate()));
        boolean bol = purchaseOrderService.save(purchaseOrder);
        if (bol) {
            Map<String, Object> map = new HashMap<>();
            map.put("type", "orderSave");
            map.put("trainingId", purchaseOrder.getTrainingid());
            String payload = objectMapper.writeValueAsString(map);
            MqttBroker.mqttClient.publish("StepInfo/supply/" + purchaseOrder.getUserid(), new MqttMessage(payload.getBytes(StandardCharsets.UTF_8)));
            return new GetMessage("成功", "200", "");
        }
        return new GetMessage("失败", "500", "");
    }

    @CrossOrigin(origins = "*", maxAge = 3600)
    @PostMapping("/updatebyid")
    public GetMessage updatebyid(@RequestBody PurchaseOrder purchaseOrder) throws JsonProcessingException, MqttException {
        boolean bol = purchaseOrderService.updateById(purchaseOrder);
        if (bol) {

            return new GetMessage("成功", "200", purchaseOrder);
        }
        return new GetMessage("失败", "500", "");
    }

    @CrossOrigin(origins = "*", maxAge = 3600)
    @GetMapping("/select")
    public GetMessage select(String userId, String trainingId, String orderNumber, String identifyCode, String isPart) throws JsonProcessingException, MqttException {
        PurchaseOrder purchaseOrder = purchaseOrderService.selectByInfo(userId, trainingId, orderNumber, identifyCode, isPart);
        if (purchaseOrder != null) {
            return new GetMessage("成功", "200", purchaseOrder);
        }
        return new GetMessage("失败", "500", "");
    }

    @CrossOrigin(origins = "*", maxAge = 3600)
    @GetMapping("/number")
    public GetMessage MakeNumber() throws JsonProcessingException, MqttException {
        SerialNumber serialNumber = serialNumberService.select("order");
        String result = "001";
        SerialNumber serialNumber1 = new SerialNumber();
        if (serialNumber != null) {
            if (Util.checkTime(serialNumber.getUpdatetime())) {
                //String[] str=serialNumber.getSerialnum().split("-");
                int num = Integer.parseInt(serialNumber.getSerialnum());
                num++;
                result = String.format("%03d", num);
                serialNumber1.setId(serialNumber.getId());
            }

        }
        serialNumber1.setSerialnum(result);
        serialNumber1.setUpdatetime(Util.getNowTime());
        serialNumber1.setType("order");
        if (serialNumber != null) {
            serialNumber1.setId(serialNumber.getId());
            serialNumberService.updateById(serialNumber1);
        } else {
            serialNumberService.save(serialNumber1);
        }
        return new GetMessage("成功", "200", "KVH-CG-XQ-" + Util.getNowTimeStr() + "-" + result);
    }
}
